﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Text.RegularExpressions;
using System.Xml;
using System.Collections.ObjectModel;

namespace DP.Sharepoint.SiteWorkflow.SSIS
{

    /// <summary>
    /// Provides methods for working with SharePoint Site workflows including getting available workflows, getting parameters for a specific worflow and starting a workflow
    /// </summary>
    public sealed class DeclarativeSiteWorkflowAssistant : IDisposable
    {
        private static readonly string SiteWorkflowServiceUrl = "_layouts/DP.Sharepoint.Workflow/SiteWorkflowActivationService.asmx";

        private SiteWorkflowActivationWS.SiteWorkflowActivationService _spProxy;

        private bool _needProxyRefresh;


        private Uri _siteUrl;

        public Uri SiteUrl
        {

            get { return _siteUrl; }

            set
            {
                if (!value.IsAbsoluteUri)
                    throw new ArgumentException("siteUrl must represent an Absolute Uri!");

                    _needProxyRefresh = true;

                    _siteUrl = value;
                
            }
        }

        /// <summary>
        /// Provides methods for working with SharePoint Site workflows including getting available workflows, getting parameters for a specific worflow and starting a workflow
        /// </summary>
        /// <param name="siteUrl">absolute url to the sharepoint site</param>
        public DeclarativeSiteWorkflowAssistant(Uri siteUrl)
        {
            SiteUrl = siteUrl;

        }

        /// <summary>
        ///
        /// </summary>
        /// <returns>list of workflows associated to the current site</returns>
        public string[] GetDeclarativeSiteWorkflowNames()
        {
            EnsureProxy();

            var res = _spProxy.GetSiteWorkflowAssociations();

            _needProxyRefresh = false;

            return res;

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="workflowName">name of the site workflow associated to the current site</param>
        /// <returns>site workflow information</returns>
        public SiteWorkflowActivationWS.SiteWorkflowInfo GetDeclarativeSiteWorkflowInfo(string workflowName)
        {
            EnsureProxy();

            var res = _spProxy.GetSiteWorkflowDetails(workflowName);

            _needProxyRefresh = false;

            return res;

        }


        /// <summary>
        /// starts SharePoint Site workflow
        /// </summary>
        /// <param name="info">workflow information object which contains populated parameters, if any</param>
        /// <param name="starter">Implementation of ISiteWorkflowStarter that has logic to call SPWorkflowManager directly or indirectly</param>
        /// <returns></returns>
        public bool StartDeclarativeSiteWorkflow(SiteWorkflowActivationWS.SiteWorkflowInfo info)
        {
            EnsureProxy();

            _spProxy.StartDeclarativeSiteWorkflow(info);

            _needProxyRefresh = false;

            return true;

        }


        private void EnsureProxy()
        {
            if (_spProxy == null || _needProxyRefresh)
                _spProxy = GetSPProxyForSPSite(SiteUrl);


            _needProxyRefresh = true;

        }

        private static SiteWorkflowActivationWS.SiteWorkflowActivationService GetSPProxyForSPSite(Uri siteUri)
        {
            var service = new SiteWorkflowActivationWS.SiteWorkflowActivationService();

            string url = siteUri.ToString();

            if (!url.EndsWith(SiteWorkflowServiceUrl))
            {
                if (!url.EndsWith("/"))
                    url += "/";

                url += SiteWorkflowServiceUrl;

            }

            service.Url = url;

            service.UseDefaultCredentials = true; // use current thread's  credentials (currently logged on user)

            return service;

        }

        public void Dispose()
        {
            try
            {
                if (_spProxy != null)
                    _spProxy.Dispose();
            }
            catch { }

        }
    }


}

